package api

import (
	"context"
	"github.com/gin-gonic/gin"
	"go-likaladi-shop/common/base_jwt"
	"go-likaladi-shop/common/base_util"
	validate "go-likaladi-shop/common/base_validate"
	"go.uber.org/zap"
	"shop-web/user-web/forms"
	"shop-web/user-web/global"
	"shop-web/user-web/global/response"
	"shop-web/user-web/proto"
	"shop-web/user-web/utils"
	"strconv"
)

func RegisterUser(ctx *gin.Context) {
	form := forms.RegisterForm{}
	if ok := validate.ValidateReqParam(&form, ctx); !ok {
		return
	}

	result, err := global.UserClient.CreateUser(context.Background(), &proto.CreateUserInfo{
		NickName: form.NickName,
		Password: form.Password,
		Mobile:   form.Mobile,
	})
	// 检查是否存在错误，如果有错误则记录日志并返回错误响应
	if base_util.IsGrpcExitError(err, ctx, "注册用户失败") {
		return // 查询失败，直接返回
	}

	base_util.RespSuccess(result, ctx)
}

func GetUserList(ctx *gin.Context) {
	zap.S().Infof("smsKey:%s, smsSecret:%s", global.ServiceYaml.AliSmsInfo.ApiKey,
		global.ServiceYaml.AliSmsInfo.ApiSecret)
	//获取请求分页属性：页数和每页显示数量
	pnInt, pSizeInt := getPageParam(ctx)
	// 通过 gRPC 远程调用获取用户列表
	rsp, err := global.UserClient.GetUserList(context.Background(), &proto.PageInfo{
		Pn:    uint32(pnInt),    // 页码，0 表示默认页
		PSize: uint32(pSizeInt), // 每页条数，0 可能表示获取所有数据
	})

	// 检查是否存在错误，如果有错误则记录日志并返回错误响应
	if base_util.IsGrpcExitError(err, ctx, "[GetUserList] 查询 【用户列表】") {
		return // 查询失败，直接返回
	}
	//parseForMap(rsp, ctx)
	//parseForObj(rsp, ctx)
	parseForObj2(rsp, ctx)
}

func MobileLogin(ctx *gin.Context) {
	loginForm := forms.MobileLoginForm{}
	if ok := validate.ValidateReqParam(&loginForm, ctx); !ok {
		return
	}

	value, ok := base_util.GetRedisValue(loginForm.SmsCode, ctx)
	if !ok {
		return
	}

	if value != loginForm.SmsCode {
		base_util.RespError("短信验证码不正确, 请重新输入", ctx)
		return
	}

	userResult, ok := getUserByMobile(loginForm.Mobile, ctx)
	if !ok {
		return
	}

	createToken(userResult, ctx)
}

func PasswordLogin(ctx *gin.Context) {
	loginForm := forms.PasswordLoginForm{}
	if ok := validate.ValidateReqParam(&loginForm, ctx); !ok {
		return
	}
	if !utils.CaptchaValidate(loginForm.CaptchaId, loginForm.Captcha, ctx) {
		return
	}
	userResult, ok := getUserByMobile(loginForm.Mobile, ctx)
	if !ok {
		return
	}

	checkResult, _ := global.UserClient.CheckPassword(ctx, &proto.PasswordCheckInfo{
		Password:          loginForm.Password,
		EncryptedPassword: userResult.Password,
	})
	if !checkResult.Success {
		base_util.RespError("密码输入错误!", ctx)
		return
	}

	createToken(userResult, ctx)
}

//func getUserClient(ctx *gin.Context) (proto.UserClient, bool) {
//	userConn, isConn := utils.IsConnSuccess("连接【用户服务】", ctx)
//	if !isConn { // 如果连接失败
//		return nil, false // 直接返回，不执行后续逻辑
//	}
//
//	// 创建 gRPC 客户端，调用 gRPC 方法时需要使用该客户端
//	userSrvClient := proto.NewUserClient(userConn)
//	return userSrvClient, true
//}

func getPageParam(ctx *gin.Context) (int, int) {
	// 获取 URL 查询参数 "pn"（页码），如果没有提供，则默认值为 "0"
	pn := ctx.DefaultQuery("pn", "0")

	// 将查询参数 "pn" 从字符串转换为整数
	// strconv.Atoi 用于将字符串转换为整数，如果转换失败，则忽略错误，默认值为 0
	pnInt, _ := strconv.Atoi(pn)

	// 获取 URL 查询参数 "pSize"（每页数量），如果没有提供，则默认值为 "10"
	pSize := ctx.DefaultQuery("pSize", "10")

	// 将查询参数 "pSize" 从字符串转换为整数
	// strconv.Atoi 同样用于转换字符串为整数，转换失败则忽略错误，默认值为 10
	pSizeInt, _ := strconv.Atoi(pSize)

	return pnInt, pSizeInt
}

func getUserByMobile(mobile string, ctx *gin.Context) (*proto.UserInfoResponse, bool) {
	userResult, err := global.UserClient.GetUserByMobile(ctx, &proto.MobileRequest{Mobile: mobile})
	// 检查是否存在错误，如果有错误则记录日志并返回错误响应
	if base_util.IsGrpcExitError(err, ctx, "[GetUserByMobile]调用失败") {
		return nil, false // 查询失败，直接返回
	}

	return userResult, true
}

func createToken(userResult *proto.UserInfoResponse, ctx *gin.Context) {
	token, ok := base_jwt.CreateToken(base_jwt.CustomClaims{
		ID:               uint(userResult.Id),
		Name:             userResult.NickName,
		AuthorityId:      uint(userResult.Role),
		RegisteredClaims: base_jwt.DefaultRegisteredClaims(),
	}, global.ServiceYaml.JwtInfo.SigningKey)
	if ok {
		base_util.RespSuccess(token, ctx)
	} else {
		base_util.RespError("登录失败", ctx)
	}
}

func parseForObj(rsp *proto.UserListResponse, ctx *gin.Context) {
	// 初始化一个空的切片，用于存储用户信息
	result := make([]interface{}, 0)

	// 遍历 gRPC 返回的用户数据
	for _, value := range rsp.Data { // 遍历返回的用户数据列表
		user := response.UserResponse{
			Id:       value.Id,
			Nickname: value.NickName,
			Birthday: utils.FormatDateTime(value.Birthday),
			Gender:   value.Gender,
			Mobile:   value.Mobile,
			Email:    value.Email,
		}
		// 将用户信息添加到结果列表
		result = append(result, user)
	}

	// 返回 JSON 响应给客户端，状态码 200，包含用户列表数据
	base_util.RespSuccess(result, ctx)
}

func parseForObj2(rsp *proto.UserListResponse, ctx *gin.Context) {
	// 初始化一个空的切片，用于存储用户信息
	result := make([]interface{}, 0)

	// 遍历 gRPC 返回的用户数据
	for _, value := range rsp.Data { // 遍历返回的用户数据列表
		user := response.UserResponse2{
			Id:       value.Id,
			Nickname: value.NickName,
			Birthday: utils.FormatDateTime2(value.Birthday),
			Gender:   value.Gender,
			Mobile:   value.Mobile,
			Email:    value.Email,
		}
		// 将用户信息添加到结果列表
		result = append(result, user)
	}

	// 返回 JSON 响应给客户端，状态码 200，包含用户列表数据
	base_util.RespSuccess(result, ctx)
}

func parseForMap(rsp *proto.UserListResponse, ctx *gin.Context) {
	// 初始化一个空的切片，用于存储用户信息
	result := make([]interface{}, 0)

	// 遍历 gRPC 返回的用户数据
	for _, value := range rsp.Data { // 遍历返回的用户数据列表
		data := map[string]interface{}{} // 创建一个 map 存储用户信息

		// 组织用户信息，将 gRPC 返回的用户数据存入 map
		data["id"] = value.Id             // 用户 ID
		data["name"] = value.NickName     // 用户昵称
		data["birthday"] = value.Birthday // 用户生日
		data["gender"] = value.Gender     // 用户性别
		data["mobile"] = value.Mobile     // 用户手机号
		data["email"] = value.Email

		// 将用户信息添加到结果列表
		result = append(result, data)
	}

	// 返回 JSON 响应给客户端，状态码 200，包含用户列表数据
	base_util.RespSuccess(result, ctx)
}
